<script setup lang="ts">
import { ref, watch } from 'vue';
import { quasarFormStyle } from '@/setting.ts';
import type {
  UserInfo,
  Role,
  AssignRolesReqData
} from '@/api/acl/user-type.ts';
import {
  reqGetUserById,
  reqSaveOrUpdateUser,
  reqGetAssignRole,
  reqDoAssignRole
} from '@/api/acl/user';
import { useQuasar } from 'quasar';
import { QForm } from 'quasar';
import { useCompRef } from '@/utils/useCompRef';

const { notify } = useQuasar();
const $emit = defineEmits<{
  refreshData: [flag?: string];
}>();
type FormType = 'SAVE' | 'UPDATE' | 'ROLE';
enum TITLE {
  SAVE = '添加用户',
  UPDATE = '更新用户',
  ROLE = '分配角色（职位）'
}
const dialogType = ref<FormType>();
const userId = ref<number>();
function showFormDialog(type: FormType, id?: number) {
  dialogType.value = type;
  userId.value = id;
  getUserInfo();
  isShowDialog.value = true;
}
defineExpose({ showFormDialog });
// 显示dialog
const isShowDialog = ref<boolean>(false);
// 用户基本信息
const userInfo = ref<UserInfo>({
  name: '',
  username: '',
  password: ''
});
const getUserInfo = async () => {
  if (!userId.value) {
    userInfo.value = {
      name: '',
      username: '',
      password: ''
    };
    return;
  }
  try {
    const result = await reqGetUserById(userId.value);
    if (result.code === 200) {
      userInfo.value = result.data;
    } else {
      throw new Error('获取用户信息失败');
    }
    if (dialogType.value === 'ROLE') {
      // 获取用户角色信息
      await getRoleInfo();
    }
  } catch (error: any) {
    notify({
      type: 'negative',
      message: error.message,
      position: 'top'
    });
  }
};
// 全部角色列表
const allRolesList = ref<Role[]>([]);
// 获取用户角色信息
async function getRoleInfo() {
  const result = await reqGetAssignRole(userId.value!);
  if (result.code === 200) {
    allRolesList.value = result.data.allRolesList;
    selectedRoles.value = result.data.assignRoles.map(role => role.id);
  } else {
    throw new Error('获取用户角色信息失败');
  }
}
// 已选角色列表
const selectedRoles = ref<number[]>([]);
// 全选
const isAllSelected = ref<'all' | 'indeterminate' | 'none'>();
watch(selectedRoles, () => {
  if (selectedRoles.value.length === allRolesList.value.length) {
    isAllSelected.value = 'all';
  } else if (selectedRoles.value.length === 0) {
    isAllSelected.value = 'none';
  } else {
    isAllSelected.value = 'indeterminate';
  }
});
// 切换全选按钮
function changeAllSelect(val: 'all' | 'none') {
  if (val === 'all') {
    selectedRoles.value = allRolesList.value.map(role => role.id);
  } else {
    selectedRoles.value = [];
  }
}

// 表单组件
const qFormCom = useCompRef(QForm);
// 提交数据
async function onSubmit() {
  const error = await qFormCom.value?.validate();
  if (!error) return;
  try {
    const requestFn =
      dialogType.value !== 'ROLE' ? reqSaveOrUpdateUser : reqDoAssignRole;
    const params =
      dialogType.value !== 'ROLE'
        ? userInfo.value
        : ({
            userId: userId.value!,
            roleIdList: selectedRoles.value
          } as AssignRolesReqData);
    const runFun = async <T extends (...args: any[]) => any>(
      fn: T,
      params: Parameters<T>[0]
    ) => {
      return await fn(params);
    };
    // requestFn(params); 报错
    const result = await runFun(requestFn, params);
    if (result.code === 200) {
      notify({
        type: 'positive',
        message: `${TITLE[dialogType.value!]}成功`,
        position: 'top'
      });
      $emit('refreshData', 'ok');
      isShowDialog.value = false;
    } else {
      throw new Error(`${TITLE[dialogType.value!]}失败`);
    }
  } catch (error: any) {
    notify({
      type: 'negative',
      message: error.message,
      position: 'top'
    });
  }
}
</script>

<template>
  <q-dialog v-model="isShowDialog">
    <q-card>
      <q-card-section>
        <span class="text-h6">{{ TITLE[dialogType!] }}</span>
      </q-card-section>
      <q-card-section>
        <q-form
          class="q-pl-lg q-gutter-xs"
          ref="qFormCom"
          style="min-width: 300px"
        >
          <q-input
            v-bind="quasarFormStyle"
            dense
            label="用户姓名"
            :readonly="dialogType === 'ROLE'"
            v-model="userInfo.name"
            :rules="[val => !!val || '用户姓名不能为空']"
          />
          <q-input
            v-bind="quasarFormStyle"
            dense
            label="用户昵称"
            v-if="dialogType !== 'ROLE'"
            v-model="userInfo.username"
            :rules="[val => !!val || '用户昵称不能为空']"
          />
          <q-input
            v-bind="quasarFormStyle"
            dense
            label="用户密码"
            v-if="dialogType === 'SAVE'"
            v-model="userInfo.password"
            :rules="[val => !!val || '用户密码不能为空']"
          />
          <div v-if="dialogType === 'ROLE'" class="relative-position">
            <q-field
              label="职位列表"
              dense
              borderless
              readonly
              class="q-ma-none"
            />
            <q-checkbox
              class="checkbox_all"
              v-model="isAllSelected"
              @update:model-value="changeAllSelect"
              true-value="all"
              indeterminate-vale="indeterminate"
              false-value="none"
            />
          </div>
          <div class="q-gutter-xs" v-if="dialogType === 'ROLE'">
            <q-checkbox
              v-for="role in allRolesList"
              :key="role.id"
              v-model="selectedRoles"
              :val="role.id"
              :label="role.roleName"
              color="primary"
            />
          </div>
        </q-form>
      </q-card-section>
      <q-card-actions align="right">
        <q-btn
          label="取消"
          color="primary"
          flat
          @click="isShowDialog = false"
        />
        <q-btn label="提交" color="primary" @click="onSubmit" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<style scoped lang="scss">
.checkbox_all {
  position: absolute;
  left: 80px;
  top: 0;
}
</style>
